<?php
/**
 * 客户端模拟并发请求投递异步任务数据
 * seq 1 20 | xargs -n 1 -P 20 curl -s -X POST -H "Content-Type: application/json" -d "{\"content\":\"2月7日，第九届亚冬会短道速滑男子1500米四分之一决赛在哈尔滨举行\",\"key1\":\"value1\",\"key2\":\"value2\"}" http://127.0.0.1:19501
 *
 * 依赖：
 * swoole4.8+
 * mysql pdo
 *
 */
 
if (!extension_loaded('swoole')) {
	throw new \Exception('Swoole扩展未安装，请先安装Swoole扩展(不支持windows环境)！版本要求4.8+');
}
$server_name = 'rewrite';

require_once 'config/database.php';
require_once 'util/http.php';
require_once 'util/zhipu.php';

// 路由表
$routes = [
	'GET' => [
		'/' => 'index',
	],
	'POST' => [
		'/api/task/push' => 'push',
	],
];

$server = new swoole_http_server("0.0.0.0", 19501);

// // //设置异步任务的工作进程数量
// // //$serv->set(array('task_worker_num' =>16,'daemonize '=> 0,));
$server->set([
    'worker_num' => 8,  //worker进程数（task_count/worker_num）worker进程数量一般设置为服务器CPU数的1-4倍
    'task_worker_num' => 60, //异步任务进程数(越多越快，注意CPU内存开销瓶颈)
    //'daemonize '=> 1,//daemonize 只在linux环境有效(且需要开启daemonize对应的类库加载)
    'max_wait_time' => 60,
    //'max_request' => 2000,
    'reload_async' => true,//异步安全重启
    //'task_enable_coroutine' => true, // task启用协程支持,可能有问题
    //'dispatch_mode' => 3,//抢占模式，主进程会根据Worker的忙闲状态选择投递，只会投递给处于闲置状态的Worker
    //"task_ipc_mode " => 1, // 使用Unix Socket通信，默认模式
    //"log_file" => "log/taskqueueu.log" ,//日志
    'package_max_length' => 1024 * 1024 * 10 * 10 * 10,
    //设置文件上传的临时目录
    'upload_tmp_dir' => __DIR__ . '/uploads/',
]);


$server->on("start", function () {
    echo "Swoole http server is started at http://0.0.0.0:19501\n";
});

// // //监听数据接收事件
$server->on('request', function(swoole_http_request $request, swoole_http_response $response) use ($server, $routes) {
    // 获取请求头信息
    // $request->header
    // 获取请求方法
    // $method = $request->server['request_method'];
    // // 获取请求的 URI
    // $uri = $request->server['request_uri'];
    // // 获取 GET 参数
    // $query = $request->get;
    // // 获取 POST 参数（需要设置 Content-Type 为 application/x-www-form-urlencoded 或 multipart/form-data 否则无法获取）
    // $post = $request->post;
    // // 设置响应内容并发送响应
    // $response->end("Method: {$method}, URI: {$uri}, Query: " . json_encode($query) . ", Post: " . json_encode($post));
    //服务器URI信息
    //$server_info = $request->server;
    //获取原始请求post数据相当于fopen('php://input');（Content-Type: application/json或非标准请求参数建议使用）
    // $json = $request->rawContent();

    $method = $request->server['request_method'];
    $path = $request->server['request_uri'];

    if (isset($routes[$method][$path])) {
        $action = $routes[$method][$path];

        $data = $request->rawContent();

        if(strpos($request->server['request_uri'], '.ico') !== false) {
            $response->end("");
        }

        $taskData = [
            'uri' => $path,
            'method' => $method,
            'get' => $request->get,
            'post' => $request->post,
            'cookie' => $request->cookie,
            'files' => $request->files,
            'action' => $action,    //异步任务方法
            'data' => is_array($data) ? json_encode($data, JSON_UNESCAPED_UNICODE) : $data,//任务数据为字符串json数据
            'fd' => $request->fd, // 保存客户端连接的文件描述符
        ];

        //投递异步任务(必须是能解析成post数组的数据转为json字符串)
        $task_id = $server->task(serialize($taskData));//非阻塞
        //$task_id = $server->task(is_array($data) ? json_encode($data, JSON_UNESCAPED_UNICODE) : $data);//非阻塞
        
        echo "[INFO] push aysnc task success,task_id: {$task_id}\n";//同步代码执行
        
        $response->end("");
    } else {
        echo "[WARN] push aysnc task failed,task_id: {$task_id}\n";//同步代码执行
        $response->status(404);
        $response->end("404 Not Found");
    }
});

// 处理异步任务
$server->on('task', function (\Swoole\Server $serv, $task_id, $from_id, $data) {
    //返回任务执行的结果
    $taskData = unserialize($data);

    $action = $taskData['action'];

    //执行异步任务
    $action($taskData);

    $serv->finish($action);
});

// 处理异步任务的结果
$server->on('finish', function (\Swoole\Server $serv, $task_id, $data) {
    echo "[INFO] aysnc task [{$action}] execute success,task_id: {$task_id}\n";
});

echo "Swoole http server init [{$server_name}]\n";
$server->start();


//------------------库------------------
static $db;
function db_connect(){
	global $config;
    if(!is_null($db)) return $db;
	$dbConfig = $config['mysql'];

    $pdo = new \PDO(
        "mysql:host={$dbConfig['host']};port={$dbConfig['port']};dbname={$dbConfig['database']};charset={$dbConfig['charset']}",
        $dbConfig['user'],
        $dbConfig['password']
    );
    
    $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    
    $db = $pdo;
    return $db;
}

// 首页
function index($taskData = []){}

// //异步任务处理函数 对应 $routes['/api/task/push']='push'
function push($taskData = []){

    if(empty($taskData['data'])){
        echo "任务数据为空，无法执行任务\n";
        return false;
    }

    $data = $taskData['data'];
    
    if(is_string($data) && !empty($data)){
        $data = json_decode($data, true);
    }
    
    if(empty($data)) $data = [];

    if(empty($data['content'])){
        echo "任务内容为空，跳过任务执行\n";
        return false;
    }
	
	if(empty($config['zhipu']['key'])){
		echo "智谱AI大模型配置文件key未配置，跳过任务执行\n";
        return false;
	}
    
    $source_content = $data['content'];
    $content = '';
    $bigModel = Zhipu::instance(['token' => $config['zhipu']['key']]);
    $prompt = "请改写以下文本内容：";
    $content = $bigModel->rewrite($source_content, $prompt, 0.7, 4096);
  
    // 准备 SQL 更新语句 test
    $sql = "UPDATE test_table_1 SET status=1,content = :content WHERE id = :id";
    $stmt = db_connect()->prepare($sql);
    $stmt->bindParam(':content',$content, PDO::PARAM_STR);
    $stmt->bindParam(':id', $data['id'], PDO::PARAM_STR);
    $stmt->execute();
    
    return true;
    
    

}
